package model

import (
	"context"
	"go-im/src/helper"
	"log"
	"time"

	"go.mongodb.org/mongo-driver/bson"
)

// User 用户结构体
type UserBasic struct {
	Identity  string `bson:"_id"`
	Account   string `bson:"account"`
	Password  string `bson:"password"`
	NickName  string `bson:"nickname"`
	Sex       int    `bson:"sex"`
	Email     string `bson:"email"`
	Avatar    string `bson:"avatar"`
	CreatedAt int64  `bson:"created_at"`
	UpdatedAt int64  `bson:"updated_at"`
}

type UserQueryResponse struct {
	NickName string `json:"nickname"`
	Sex      int    `bson:"sex"`
	Email    string `bson:"email"`
	Avatar   string `bson:"avatar"`

	IsFriend bool `json:"is_friend"`
}

func (UserBasic) CollectionName() string {
	return "user_basic"
}

func GetUserBasicByAccountPassword(account, password string) (*UserBasic, error) {
	ub := new(UserBasic)
	hashedPassword := helper.GetMd5(password) // 对密码进行哈希处理
	err := InitMongo().Collection(UserBasic{}.CollectionName()).
		FindOne(context.Background(), bson.D{{
			Key:   "account",
			Value: account,
		}, {
			Key:   "password",
			Value: hashedPassword,
		}}).Decode(ub)

	return ub, err
}

func GetUserBasicByIdentity(identity string) (*UserBasic, error) {
	ub := new(UserBasic)
	err := InitMongo().Collection(UserBasic{}.CollectionName()).
		FindOne(context.Background(),
			bson.D{{"_id", identity}},
		).
		Decode(ub)
	return ub, err
}

func GetUserBasicByAccount(account string) (*UserBasic, error) {
	ub := new(UserBasic)
	err := InitMongo().Collection(UserBasic{}.CollectionName()).
		FindOne(context.Background(),
			bson.D{{"account", account}},
		).Decode(ub)

	return ub, err
}

func GetUserBasicCountByEmail(email string) (int64, error) {
	return InitMongo().Collection(UserBasic{}.CollectionName()).
		CountDocuments(context.Background(),
			bson.D{{"email", email}})
}

func GetUserBasicCountByAccount(account string) (int64, error) {
	return InitMongo().
		Collection(UserBasic{}.CollectionName()).
		CountDocuments(context.Background(),
			bson.D{{"account", account}},
		)
}

func InsertOneUserBasic(ub *UserBasic) error {
	_, err := InitMongo().Collection(UserBasic{}.CollectionName()).
		InsertOne(context.Background(), ub)
	return err
}

func JudgeUserIsFriend(userId1, userId2 string) bool {
	// query userid1 chat room list
	cursor, err := Mongo.Collection(UserRoom{}.
		CollectionName()).
		Find(context.Background(), bson.D{
			{"user_identity", userId1},
			{
				"room_type", 1,
			}})
	roomIdentities := make([]string, 0)

	if err != nil {
		log.Println("failed to get user room: ", err)
		return false
	}

	for cursor.Next(context.Background()) {
		ur := new(UserRoom)
		err := cursor.Decode(ur)
		if err != nil {
			log.Println("failed to get user room", err)
			return false
		}

		roomIdentities = append(roomIdentities, ur.RoomIdentity)
	}

	// get userId2 rooms
	cnt, err := Mongo.Collection(UserRoom{}.CollectionName()).
		CountDocuments(
			context.Background(),
			bson.M{
				"user_identity": userId2,
				"room_type":     1,
				"room_identity": bson.M{"$in": roomIdentities},
			})

	if err != nil {
		log.Println("failed to get user room: ", err)
		return false
	}

	// yes friends
	if cnt > 0 {
		return true
	}

	return false
}

func UpdateUserProfile(identity, nickname string, sex int, avatar string) error {
	collection := Mongo.Collection(UserBasic{}.CollectionName())

	update := bson.D{
		{"$set", bson.D{
			{"nickname", nickname},
			{"sex", sex},
			{"avatar", avatar},
			{"updated_at", time.Now().Unix()},
		}},
	}
	log.Println(update)
	_, err := collection.UpdateOne(context.Background(), bson.D{{"_id", identity}}, update)
	return err
}
